home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Free Software Collection: Marty 1
/
FM Towns Marty 1 Free Software Collection.iso
/
tool
/
book
/
src
/
event.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-11-11
|
12KB
|
506 lines
/*
* マウス イベント処理ライブラリ
*
* 1990.9.11 Make By ken
*/
#include <stdio.h>
#include <stdefs.h>
#include <stdlib.h>
#include <math.h>
#include <egb.h>
#include <mos.h>
#include <msdos.cf>
#include "event.h"
#include "book.h"
#include "snd.h"
#include "mouse.h"
static evt_t *last_node = NULL ;
static evt_t evt_node = { NULL,NULL } ;
static int time_counter = 0 ;
static int interval_limit = 2 ;
static int enable_cancel = TRUE ;
static int enable_ground = FALSE ;
static EVT cancel = { NULL,NULL } ;
static EVT ground = { NULL,NULL } ;
struct {
short int level ; /* イベントレベル */
void (*proc)() ; /* 処理関数 */
} interval = { -1, (void (*)())0 } ;
/* ボタン状態の検査 */
int lbtn(int sw) /* 左ボタンが押されていたら、TRUE */
{
return (sw & 1) != 0 ? TRUE:FALSE;
}
int rbtn(int sw) /* 右ボタンが押されていたら、TRUE */
{
return (sw & 2) != 0 ? TRUE:FALSE;
}
/* イベントの発生をチェック */
static int EVT_chk( REGS evt_t *ep, int x, int y, int sw )
{
int on ;
on = ( x >= ep->x1 && x <= ep->x2 &&
y >= ep->y1 && y <= ep->y2 ) ? TRUE : FALSE ;
switch( ep->now )
{
case Ev_OFF_MOS:
case Ev_MOVE_MOS:
case Ev_DLSEL_MOS:
case Ev_SELECT_MOS:
ep->now = Ev_NON ;
break ;
case Ev_NON:
if( on == TRUE )
{
ep->now = ( sw != 0 ? Ev_CLIP_MOS:Ev_ON_MOS ) ;
(*ep->proc)( ep, x, y, sw ) ;
}
break ;
case Ev_ON_MOS:
if( on == TRUE )
{
if( sw != 0 )
{
ep->now = Ev_CLIP_MOS ;
(*ep->proc)( ep, x, y, sw ) ;
}
}
else
{
ep->now = Ev_OFF_MOS ;
(*ep->proc)( ep, x, y, sw ) ;
}
break ;
case Ev_CLIP_MOS:
if( on == TRUE )
{
if( sw == 0 ) /* ボタンを離した */
{
ep->now = Ev_SELECT_MOS ;
(*ep->proc)( ep, x, y, sw ) ;
}
}
else
{
ep->now = ( sw != 0 ? Ev_DOLACK_MOS : Ev_MOVE_MOS ) ;
(*ep->proc)( ep, x, y, sw ) ;
}
break ;
case Ev_DOLACK_MOS:
if( sw == 0 ) /* ボタンを離した */
{
ep->now = Ev_DLSEL_MOS ;
(*ep->proc)( ep, x, y, sw ) ;
}
break ;
case Ev_REP_MOS:
if( on == TRUE )
{
if( sw == 0 ) /* ボタンを離した */
{
ep->now = Ev_SELECT_MOS ;
(*ep->proc)( ep, x, y, sw ) ;
}
else
(*ep->proc)( ep, x, y, sw ) ;
}
else
{
ep->now = ( sw == 0 ? Ev_DOLACK_MOS : Ev_MOVE_MOS ) ;
(*ep->proc)( ep, x, y, sw ) ;
}
break ;
}
return ep->now ;
}
static EVT *EVT_chk_evt( EVT *cp, int min, int max )
{
for( ; cp != NULL ; cp = cp->next )
if( cp->level >= min && cp->level <= max )
return cp ;
return NULL ;
}
static void int_counter(void)
{
static int a = 0;
if (interval_limit > 0 && ++a >= interval_limit)
a = 0, time_counter++;
}
void EVT_loop(int min_level, int max_level)
{
evt_t *ep;
EVT *cp;
int x, y;
static int sw = 0, l_on = FALSE, r_on = FALSE;
static int time = 0;
if( !enable_cancel )
r_on = rbtn( sw ) ;
l_on = lbtn( sw ) ;
mos_rdpos( &sw, &x, &y ) ;
/* インターバル割り込み */
if( !islock( last_node ) &&
interval.level >= min_level && interval.level <= max_level &&
time != time_counter )
{
time = time_counter ;
(*interval.proc)() ;
}
/* 右クリックによるキャンセル機能 */
if( enable_cancel )
{
if( cancel.next != NULL && r_on && rbtn( sw ) == FALSE )
{
cp = EVT_chk_evt( cancel.next, min_level, max_level ) ;
cp->proc() ;
}
r_on = rbtn( sw ) ;
sw &= 1 ;
}
/* 前回のイベントの継続? */
if( last_node != NULL &&
last_node->level >= min_level && last_node->level <= max_level &&
EVT_chk( last_node, x, y, sw ) == Ev_REP_MOS && islock( last_node ) )
return ;
/* イベント発生の検査 */
for( ep = evt_node.next ; ep != NULL ; ep = ep->next )
if( ep->level >= min_level && ep->level <= max_level &&
EVT_chk( ep, x, y, sw ) != Ev_NON )
{
last_node = ep ;
return ;
}
last_node = NULL ;
/* 余白のクリックによるイベント */
if( enable_ground )
{
if( ground.next != NULL )
{
cp = EVT_chk_evt( ground.next, min_level, max_level ) ;
if( cp != NULL && (
( isright(cp) && r_on && rbtn( sw ) == FALSE ) ||
( isleft( cp) && l_on && lbtn( sw ) == FALSE ) ) )
{
cp->proc() ;
r_on = rbtn( sw ) ;
}
}
}
return ;
}
/* イベントの登録・調査とレベル解除、全解除 */
static evt_t *EVT_get_new_node( int level )
{ /* レベルの高い順にソートされるよう、挿入する */
evt_t *tp, *ep ;
ep = &evt_node ;
for( tp = ep->next ; tp != NULL ; tp = tp->next )
{
if( tp->level < level )
break ;
ep = tp ;
}
if( ( tp = malloc( sizeof( evt_t ) ) ) != NULL )
{
tp->next = ep->next ;
tp->back = ep ;
ep->next = tp ;
if( tp->next != NULL )
(tp->next)->back = tp ;
return tp ;
}
return NULL ;
}
static void EVT_free_node( evt_t *ep )
{
(ep->back)->next = ep->next ;
if( ep->next != NULL )
(ep->next)->back = ep->back ;
free( ep ) ;
if( ep == last_node )
last_node = NULL ;
}
static void EVT_free_node_evt( EVT *cp )
{
(cp->back)->next = cp->next ;
if( cp->next != NULL )
(cp->next)->back = cp->back ;
free( cp ) ;
}
static void EVT_reset_evt( EVT *cp )
{
EVT *np ;
for( ; cp != NULL ; cp = np )
{
np = cp->next ;
EVT_free_node_evt( cp ) ;
}
}
#if 0
void EVT_print_list( void )
{
evt_t *ep ;
ep = evt_node.next ;
while( ep != NULL )
{
printf( "level = %d, num = %d\n", ep->level, ep->no ) ;
ep = ep->next ;
}
printf( "\n\n" ) ;
}
#endif
evt_t *EVT_set_node( int x1, int y1, int xs, int ys,
int level, void (*proc)(), mevt_t no, int rep)
{
evt_t *ep ;
if( ( ep = EVT_get_new_node( level ) ) != NULL )
{
ep->flag = rep ;
ep->level = level ;
ep->now = Ev_NON ;
ep->no = no ;
ep->x1 = x1 ;
ep->y1 = y1 ;
ep->x2 = x1+xs ;
ep->y2 = y1+ys ;
ep->proc = proc ;
}
return ep ;
}
evt_t *EVT_get_node( int level, mevt_t no )
{ /* 指定レベルの指定番号のイベントデータを返す */
evt_t *ep;
for (ep = evt_node.next; ep != NULL; ep = ep->next)
if (ep->level == level && ep->no == no)
return ep;
return NULL;
}
void EVT_level_free( int level )
{
REGS evt_t *ep, *tp ;
for( ep = evt_node.next ; ep != NULL ; ep = tp )
{
tp = ep->next ;
if( ep->level == level )
EVT_free_node( ep ) ;
}
EVT_unset_cancel( level ) ;
EVT_unset_ground( level ) ;
}
void EVT_reset( void )
{
evt_t *ep, *tp ;
EVT_control_cancel( ON ) ;
EVT_control_ground( OFF ) ;
EVT_unset_interval() ;
for( ep = evt_node.next ; ep != NULL ; ep = tp )
{
tp = ep->next ;
EVT_free_node( ep ) ;
}
EVT_reset_evt( cancel.next ) ;
EVT_reset_evt( ground.next ) ;
}
void BTN_set( int x,int y, int xs,int ys, int wind_col,
int lev, void (*proc)(), mevt_t evt, int rep )
{
dsp_box( x,y, x+xs,y+ys, BOX1_COL,BOX2_COL,wind_col ) ;
EVT_set_node( x,y, xs,ys, lev,proc,evt, rep ) ;
}
/* キャンセル/余白検出の登録・解除・制御 */
static EVT *EVT_get_new_node_evt( EVT *root )
{
EVT *tp ;
if( ( tp = malloc( sizeof( EVT ) ) ) != NULL )
{
tp->next = root->next ;
tp->back = root ;
root->next = tp ;
if( tp->next != NULL )
(tp->next)->back = tp ;
return tp ;
}
return NULL ;
}
static void EVT_level_free_evt( EVT *cp, int level )
{
REGS EVT *np ;
for( ; cp != NULL ; cp = np )
{
np = cp->next ;
if( cp->level == level )
EVT_free_node_evt( cp ) ;
}
}
int EVT_control_cancel( int flag )
{
int org_mode = enable_cancel ;
enable_cancel = flag ;
return org_mode ;
}
int EVT_control_ground( int flag )
{
int org_mode = enable_ground ;
enable_ground = flag ;
return org_mode ;
}
void EVT_set_cancel( int level, void (*proc)() )
{
EVT *cp ;
if( ( cp = EVT_get_new_node_evt( &cancel ) ) != NULL )
{
cp->level = level ;
cp->proc = proc ;
}
}
void EVT_set_ground( int level, void (*proc)(), int sw )
{
EVT *cp ;
if( ( cp = EVT_get_new_node_evt( &ground ) ) != NULL )
{
cp->level = level ;
cp->sw = sw ;
cp->proc = proc ;
}
}
void EVT_unset_cancel( int level )
{
EVT_level_free_evt( cancel.next, level ) ;
}
void EVT_unset_ground( int level )
{
EVT_level_free_evt( ground.next, level ) ;
}
/* インターバル割り込みの登録と解除 */
#ifdef VSYNC
# include "vsync.h"
#endif
int EVT_set_interval(int level, int value, void (*proc)())
{
int counter, absolute;
#ifdef VSYNC
VSYNC_setEvent((void (*)())int_counter);
#else
SND_int_timer_a_set((void (*)())int_counter);
#endif
interval.level = level;
interval.proc = proc;
absolute = abs(value);
counter = 1000-3000/(absolute+3);
/* 1000 - 1000/value 1->1 10->900 100->990 */
/* 1000 - 3000/(value+3) 0->1 10->769 100->970 */
/* 1000 - 5000/(value+5) 0->1 10->666 100->952 */
if (counter > 1000)
counter = 1000;
#ifdef VSYNC
#else
SND_fm_timer_a_set(1, counter);
#endif
if (absolute < 20)
interval_limit = 3;
else if (absolute < 60)
interval_limit = 2;
else
interval_limit = 1;
#if 0
static char buf[256];
sprintf(buf, " value %3d/counter %3d ", absolute, counter);
wrt(buf, 0,0, 15,1, 16);
#endif
return absolute < 100 ? (value / absolute) : (value / 40) ;
}
void EVT_unset_interval( void )
{
interval.level = -1;
#ifdef VSYNC
#else
SND_fm_timer_a_set(0, 1);
#endif
}
#if 0
/* デバッグ用リスト表示ルーチン */
void EVT_print( void )
{
evt_t *ep ;
for( ep = evt_node.next ; ep != NULL ; ep = ep->next )
printf( "level %3d/flag %2d/no %3d (%3d-%3d)-(%3d-%3d)\n",
ep->level, ep->flag, ep->no, ep->x1,ep->y1, ep->x2,ep->y2 ) ;
}
#endif